package practice;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PhoneBook {
    private static final Pattern PATTERN_PHONE = Pattern.compile(" *\\+?\\d.*");
    private static final Pattern PATTERN_NAME = Pattern.compile(" *\\p{L}[\\p{L} ]*");

    private final HashMap<String, String> phone2name = new HashMap<>();

    public void addContact(String phone, String name) {
        // проверьте корректность формата имени и телефона
        // (рекомедуется написать отдельные методы для проверки является строка именем/телефоном)
        // если такой номер уже есть в списке, то перезаписать имя абонента

        if (!isPhone(phone) || !isName(name)) {
            return;
        }

        phone2name.put(phone2key(phone), name);
    }

    public String getContactByPhone(String phone) {
        // формат одного контакта "Имя - Телефон"
        // если контакт не найдены - вернуть пустую строку

        String key = phone2key(phone);
        String name = phone2name.get(key);

        return name != null ? name + " - " + key : "";
    }

    public Set<String> getContactByName(String name) {
        // формат одного контакта "Имя - Телефон"
        // если контакт не найден - вернуть пустой TreeSet

        TreeSet<String> contacts = new TreeSet<>();

        for (Map.Entry<String, String> entry : phone2name.entrySet()) {
            if (entry.getValue().compareTo(name) == 0) {
                contacts.add(entry.getValue() + " - " + entry.getKey());
            }
        }

        return contacts;
    }

    public Set<String> getAllContacts() {
        // формат одного контакта "Имя - Телефон"
        // если контактов нет в телефонной книге - вернуть пустой TreeSet

        TreeSet<String> contacts = new TreeSet<>();
        Set<String> names = getAllNames();

        for (String name : names) {
            contacts.add(name + " - " + phonesToString(getPhoneByName(name)));
        }

        return contacts;
    }

    // для обхода Map используйте получение пары ключ->значение Map.Entry<String,String>
    // это поможет вам найти все ключи (key) по значению (value)
    /*
        for (Map.Entry<String, String> entry : map.entrySet()){
            String key = entry.getKey(); // получения ключа
            String value = entry.getValue(); // получения ключа
        }
    */

    public static String phone2key(String phone) {
        return phone.replaceAll("[^\\d]", "");
    }

    public static boolean isPhone(String phone) {
        Matcher matcher = PATTERN_PHONE.matcher(phone);
        return matcher.matches();
    }

    public static boolean isName(String name) {
        Matcher matcher = PATTERN_NAME.matcher(name);
        return matcher.matches();
    }

    public boolean containsPhone(String phone) {
        String key = phone2key(phone);
        return phone2name.containsKey(key);
    }

    public boolean containsName(String name) {
        return phone2name.containsValue(name);
    }

    public String getNameByPhone(String phone) {
        String key = phone2key(phone);
        String name = phone2name.get(key);

        return name != null ? name : "";
    }

    public Set<String> getPhoneByName(String name) {
        TreeSet<String> phones = new TreeSet<>();

        for (Map.Entry<String, String> entry : phone2name.entrySet()) {
            if (entry.getValue().compareTo(name) == 0) {
                phones.add(entry.getKey());
            }
        }

        return phones;
    }

    public Set<String> getAllNames() {
        return new TreeSet<>(phone2name.values());
    }

    public static String phonesToString(Set<String> phones) {
        StringJoiner contact = new StringJoiner(", ");

        for (String phone : phones) {
            contact.add(phone);
        }

        return contact.toString();
    }
}